

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include <stdio.h>
volatile uint32_t timer0_counter = 0;
volatile uint32_t timer1_counter = 0;
volatile uint32_t timer2_counter = 0;
volatile uint32_t timer3_counter = 0;

volatile uint32_t systick_precedent = 0;

void enable_timer(uint8_t timer_num);
void disable_timer(uint8_t timer_num);
void init_timer (uint8_t timer_num, uint32_t TimerInterval);
void reset_timer(uint8_t timer_num);

void TIMER0_IRQHandler(void);
void TIMER1_IRQHandler(void);
void TIMER2_IRQHandler(void);
void TIMER3_IRQHandler(void);

#define TIMER0_INTERVAL 25000000 //  ((2 * (4 *(SystemCoreClock/10))) - 1)
#define TIMER1_INTERVAL	 ((2 *(4 *(SystemCoreClock/10))/3) - 1)
#define TIMER2_INTERVAL	 ((2 *(4 *(SystemCoreClock/10))/5) - 1)
#define TIMER3_INTERVAL	 ((2 *(4 *(SystemCoreClock/10))/7) - 1)

#define PCTIM0_POWERON (1 << 1)
#define PCTIM1_POWERON (1 << 2)
#define PCTIM2_POWERON (1 << 22)
#define PCTIM3_POWERON (1 << 23)

void SysTick_Handler(void)
{
	printf("SYSTICK\n !");
	SysTick->LOAD = 0xFFFFF;
}
int main(void)
{
	
	// Turn on power to TIMER2 and TIMER3
	// (TIMER0 and TIMER1 on by default)
	//LPC_SC->PCONP |=  PCTIM2_POWERON | PCTIM3_POWERON;

	// SysTick Page 783
	SysTick->LOAD = 0xFFFFF;
	SysTick->CTRL = 5; //+2;  // si +2 => interruption SysTickHandler activee

	// RTC
	 LPC_RTC->DOW = 1;
	 LPC_RTC->MONTH = 8;
     LPC_RTC->YEAR = 2012;


	init_timer( 0, TIMER0_INTERVAL );
	printf("Reglages Timer 0:\n");
	printf("PCLK (Peripheral Clock Selection) = %d\n",(LPC_SC->PCLKSEL0 & 12)); // bit 2 et 3 pour TIMER 0
	// si bit 3 et 4 a zero -> PCLKSEL0 = CCLK/4
	printf("PR (PRESCALER REGISTER) = %d\n", LPC_TIM0->PR);
	printf("PC (PRESCALER COUNTER)  = %d\n", LPC_TIM0->PC);
	

	enable_timer( 0 );

	// Enter an infinite loop, just incrementing a counter
	volatile static int i = 0 ;
	while(1) {
		i++ ;
	}
	return 0 ;
}


void enable_timer( uint8_t timer_num )
{	init_timer( 0, TIMER0_INTERVAL );
	if ( timer_num == 0 )
	{
		LPC_TIM0->TCR = 1;
	}
	else if ( timer_num == 1 )
	{
		LPC_TIM1->TCR = 1;
	}
	else if ( timer_num == 2 )
	{
		LPC_TIM2->TCR = 1;
	}
	else if ( timer_num == 3 )
	{
		LPC_TIM3->TCR = 1;
	}
}

void disable_timer( uint8_t timer_num )
{
	if ( timer_num == 0 )
	{
		LPC_TIM0->TCR = 0;
	}
	else if ( timer_num == 1 )
	{
		LPC_TIM1->TCR = 0;
	}
	else if ( timer_num == 2 )
	{
		LPC_TIM2->TCR = 0;
	}
	else if ( timer_num == 3 )
	{
		LPC_TIM3->TCR = 0;
	}
}

void reset_timer( uint8_t timer_num )
{
	uint32_t regVal;

	if ( timer_num == 0 )
	{
		regVal = LPC_TIM0->TCR;
		regVal |= 0x02;
		LPC_TIM0->TCR = regVal;
	}
	else if ( timer_num == 1 )
	{
		regVal = LPC_TIM1->TCR;
		regVal |= 0x02;
		LPC_TIM1->TCR = regVal;
	}
	else if ( timer_num == 2 )
	{
		regVal = LPC_TIM2->TCR;
		regVal |= 0x02;
		LPC_TIM2->TCR = regVal;
	}
	else if ( timer_num == 3 )
	{
		regVal = LPC_TIM3->TCR;
		regVal |= 0x02;
		LPC_TIM3->TCR = regVal;
	}
}


void init_timer ( uint8_t timer_num, uint32_t TimerInterval )
{
	if ( timer_num == 0 )
	{
		timer0_counter = 0;
		LPC_TIM0->MR0 = TimerInterval;
		LPC_TIM0->MCR = 3;				/* Interrupt and Reset on MR0 */
		NVIC_EnableIRQ(TIMER0_IRQn);
	}
	else if ( timer_num == 1 )
	{
		timer1_counter = 0;
		LPC_TIM1->MR0 = TimerInterval;
		LPC_TIM1->MCR = 3;				/* Interrupt and Reset on MR1 */
		NVIC_EnableIRQ(TIMER1_IRQn);
	}
	else if ( timer_num == 2 )
	{
		timer2_counter = 0;
		LPC_TIM2->MR0 = TimerInterval;
		LPC_TIM2->MCR = 3;				/* Interrupt and Reset on MR1 */
		NVIC_EnableIRQ(TIMER2_IRQn);
	}
	else if ( timer_num == 3 )
	{
		timer3_counter = 0;
		LPC_TIM3->MR0 = TimerInterval;
		LPC_TIM3->MCR = 3;				/* Interrupt and Reset on MR1 */
		NVIC_EnableIRQ(TIMER3_IRQn);
	}
}

void TIMER0_IRQHandler (void)
{
  LPC_TIM0->IR = 1;			/* clear interrupt flag */
  timer0_counter++;
  uint32_t diff = SysTick->VAL - systick_precedent;
  printf("#%d TIMER0 - CCLK = %d, INTERVAL = %d, SysTick = %d, DIFF=%d\n",timer0_counter, SystemCoreClock, TIMER0_INTERVAL, SysTick->VAL, diff);
  printf("RTC %02d/%02d/%02d - %02d:%02d:%02d\n", LPC_RTC->DOM, LPC_RTC->MONTH, LPC_RTC->YEAR, LPC_RTC->HOUR,LPC_RTC->MIN,LPC_RTC->SEC);
  systick_precedent = SysTick->VAL;
  //SysTick->LOAD = 10000;
  return;
}

void TIMER1_IRQHandler (void)
{
  LPC_TIM1->IR = 1;			/* clear interrupt flag */
  timer1_counter++;
  return;
}

void TIMER2_IRQHandler (void)
{
  LPC_TIM2->IR = 1;			/* clear interrupt flag */
  timer2_counter++;
  return;
}
void TIMER3_IRQHandler (void)
{
  LPC_TIM3->IR = 1;			/* clear interrupt flag */
  timer3_counter++;
  return;
}
